package com.tudouji.framework.task;

import com.tudouji.common.utils.DateUtils;
import com.tudouji.project.customer.service.ICustomerService;
import com.tudouji.project.mt.domain.*;
import com.tudouji.project.mt.service.*;
import com.tudouji.project.organization.service.IOrganizationService;
import com.tudouji.project.organization.service.ISupplierService;
import com.tudouji.project.product.service.ISalesspecificationService;
import com.tudouji.project.store.service.IStockunitService;
import com.tudouji.project.store.service.IStorehouseroomService;
import com.tudouji.project.store.service.IStoreroomService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;


/**
 * 根据美团菜品消耗表，加工美团成本卡
 */
@Service
@Slf4j
public class MeituanCostcardProcessing {
    @Autowired
    private ISupplierService supplierService;

    @Autowired
    private MeituanDataProcessUtil meituanDataProcessUtil;

    @Autowired
    private IOrganizationService organizationService;

    @Autowired
    private ICustomerService customerService;

    @Autowired
    private ISalesspecificationService salesspecificationService;

    @Autowired
    private IStoreroomService storeroomService;

    @Autowired
    private IStorehouseroomService storehouseroomService;

    @Autowired
    private IStockunitService stockunitService;

    @Autowired
    private IMtShopService mtShopService;

    @Autowired
    private IMtWhinService mtWhinService;
    @Autowired
    private IMtWhinitemService mtWhinitemService;

    @Autowired
    private IMtWhoutService mtWhoutService;
    @Autowired
    private IMtWhoutitemService mtWhoutitemService;

    @Autowired
    private IMtFoodconsumService mtFoodconsumService;
    @Autowired
    private IMtFoodconsumitemService mtFoodconsumitemService;
    @Autowired
    private IMtFoodconsumgoodsitemService mtFoodconsumgoodsitemService;
    @Autowired
    private IMtFoodcostcardService mtFoodcostcardService;
    @Autowired
    private IMtFoodcostcarditemService mtFoodcostcarditemService;



    /**
     * 根据美团菜品消耗表，生成美团成本卡数据
     */
    public void costCardProcess(){
        MtShop lookup = new MtShop();
        lookup.setStatus(1);
        List<MtShop> mtShopList = mtShopService.selectMtShopList(lookup);
        for(MtShop mtShop:mtShopList){
            costcardProcessForShop(mtShop);
        }
    }

    /**
     * 处理某一店铺的入库单
     * @param mtShop
     */
    @Transactional
    public void costcardProcessForShop(MtShop mtShop){
        MtFoodconsum lookup = new MtFoodconsum();
        //设置查询条件，查询状态为 1 - 初始 的美团菜品消耗单主表数据
        //需要有时间范围，仅查询推送数据前 n 天 到当前的数据即可  （应该是大于等于推送日期即可）
        Long startBiztime = DateUtils.addDays(mtShop.getPushdate(),0).getTime();

        lookup.setStartBiztime(startBiztime);
        lookup.setMtShopld(mtShop.getId());
        //lookup.setStatus(1);
        List<MtFoodconsum> mtFoodconsums = mtFoodconsumService.selectMtFoodconsumList(lookup);
        for(MtFoodconsum mtFoodconsum:mtFoodconsums){
            if(mtFoodconsum.getStatus()!=1 ){
                continue;
            }
            costcardProcessForconsumOrder(mtFoodconsum,mtShop);
            //更新主表数据,处理完成
            mtFoodconsum.setStatus(100);
            mtFoodconsumService.updateMtFoodconsum(mtFoodconsum);
        }
    }

    /**
     * 处理每天菜品消耗数据
     */
    private boolean costcardProcessForconsumOrder(MtFoodconsum mtFoodconsum, MtShop mtShop) {

        //获取菜品消耗明细表
        MtFoodconsumitem lookup = new MtFoodconsumitem();
        lookup.setMtFoodconsumid(mtFoodconsum.getId());
        List<MtFoodconsumitem> mtFoodconsumitems = mtFoodconsumitemService.selectMtFoodconsumitemList(lookup);
        for(MtFoodconsumitem mtfoodconsumitem:mtFoodconsumitems){
            //处理美团菜品消耗单明细表，针对每一菜品处理成本卡
            costcardProcessForconsumItem(mtFoodconsum,mtfoodconsumitem,mtShop);
            mtFoodconsumitemService.updateMtFoodconsumitem(mtfoodconsumitem);
        }
        return true;
    }


    /**
     * 处理菜品消耗明细数据，检查并生成该菜品的成本卡
     * @param mtFoodconsum           菜品消耗主表数据
     * @param mtfoodconsumitem       菜品消耗明细表数据
     * @param mtShop                 美团店铺
     */
    private void costcardProcessForconsumItem(MtFoodconsum mtFoodconsum,MtFoodconsumitem mtfoodconsumitem,MtShop mtShop){
        //获取美团菜品消耗明细表对应的物品信息
        MtFoodconsumgoodsitem lookup = new MtFoodconsumgoodsitem();
        lookup.setMtFoodconsumitemid(mtfoodconsumitem.getId());
        List<MtFoodconsumgoodsitem> mtFoodconsumgoodsitems = mtFoodconsumgoodsitemService.selectMtFoodconsumgoodsitemList(lookup);

        //获取到菜品消耗明细表对应的子表 - 物品消耗信息后，开始处理
        doProcessCostcard(mtFoodconsum,mtfoodconsumitem,mtFoodconsumgoodsitems,mtShop);

    }

    /**
     * 针对菜品消耗明细、以及其包含的货品消耗信息，处理该产品的成本卡数据
     * @param mtfoodconsum            菜品消耗主表数据
     * @param mtFoodconsumitem        菜品消耗明细表数据
     * @param goodsitems              菜品消耗明细表数据对应的物品消耗明细数据
     * @param mtshop                  美团店铺
     * @return
     */
    private boolean doProcessCostcard(MtFoodconsum mtfoodconsum,
                                      MtFoodconsumitem mtFoodconsumitem, List<MtFoodconsumgoodsitem> goodsitems,MtShop mtshop){
        boolean needToCreate = false;
        //获取当前菜品的最后一条成本卡数据
        MtFoodcostcard lookup = new MtFoodcostcard();
        lookup.setFoodskuid(mtFoodconsumitem.getFoodskuid());
        List<MtFoodcostcard> mtFoodcostcards = mtFoodcostcardService.selectMtFoodcostcardList(lookup);
        if(mtFoodcostcards.size()!=0){
            //获取到该菜品的第一条成本卡数据，比较成本卡数据是否有变化
            MtFoodcostcard existCard = mtFoodcostcards.get(0);
            //获取已存在的成本卡的物品配置信息
            MtFoodcostcarditem fclookup = new MtFoodcostcarditem();
            fclookup.setMtFoodcostcardid(existCard.getId());
            List<MtFoodcostcarditem> existCardItems = mtFoodcostcarditemService.selectMtFoodcostcarditemList(fclookup);

            //检查当前菜品消耗表的业务日期，如果已经小于成本卡日期，不需要处理了
            if(mtfoodconsum.getBiztime()<existCard.getEffectiveDate().getTime()){
                log.info("菜品消耗表业务日期小于已存在的成本卡生效日期！");
                mtFoodconsumitem.setRemark("菜品消耗表业务日期小于已存在的成本卡生效日期！");
                return true;
            }
            if(!costcardChanged(existCard,existCardItems,mtFoodconsumitem,goodsitems,mtshop)){
                //没变化，不需要新增
                mtFoodconsumitem.setRemark("菜品成本无变化，不需要生成成本卡！");
                return true;
            }
        }

        //成本卡有变化，或者当前菜品尚未生成成本卡数据，需要新增
        MtFoodcostcard newCard = new MtFoodcostcard();

        prepareFoodCostCard(newCard,mtfoodconsum,mtFoodconsumitem);
        //主表数据入库
        mtFoodcostcardService.insertMtFoodcostcard(newCard);
        generatefoodcostcardItem(newCard,mtFoodconsumitem,goodsitems);

        mtFoodconsumitem.setRemark("已经生成成本卡:"+newCard.getId());
        return true;
    }

    /**
     * 根据美团菜品消耗明细表、以及物料消耗明细表，生成美团成本卡明细数据
     * @param newCard
     * @param mtFoodconsumitem
     * @param goodsitems
     */
    private void generatefoodcostcardItem(MtFoodcostcard newCard,
                                          MtFoodconsumitem mtFoodconsumitem, List<MtFoodconsumgoodsitem> goodsitems) {
        for(MtFoodconsumgoodsitem consumgoodsitem:goodsitems){
            MtFoodcostcarditem costcarditem = new MtFoodcostcarditem();
            costcarditem.setMtFoodcostcardid(newCard.getId());
            costcarditem.setFoodskuid(newCard.getFoodskuid());
            costcarditem.setFoodname(newCard.getFoodname());

            costcarditem.setMtGoodsCode(consumgoodsitem.getMtGoodsCode());
            costcarditem.setMtGoodsName(consumgoodsitem.getMtGoodsName());

            costcarditem.setBaseunitId(consumgoodsitem.getBaseunitId());
            costcarditem.setBaseunitName(consumgoodsitem.getBaseunitName());

            //计算美团菜品消耗物品明细表中该菜品的成本卡消耗数量、也就是每一份菜品消耗的物品数量
            setConsumptionamountInCostCard(mtFoodconsumitem,consumgoodsitem);
            costcarditem.setAmount(consumgoodsitem.getConsumptionamountInCostcard());

            costcarditem.setCreateBy("1");
            costcarditem.setCreateTime(DateUtils.getNowDate());

            mtFoodcostcarditemService.insertMtFoodcostcarditem(costcarditem);
        }
    }

    /**
     * 判断成本卡是否有变化
     * @param existCardItems
     * @param goodsitems
     * @return
     */
    private boolean costcardChanged(MtFoodcostcard existCard, List<MtFoodcostcarditem> existCardItems,MtFoodconsumitem newCard,
                                    List<MtFoodconsumgoodsitem> goodsitems,MtShop mtShop) {
        if(existCardItems.size()!=goodsitems.size()){
            return true;
        }
        //条数一样，判断内容
        //1.排序
        Collections.sort(existCardItems, new Comparator<MtFoodcostcarditem>() {
            @Override
            public int compare(MtFoodcostcarditem o1, MtFoodcostcarditem o2) {
                return o1.getMtGoodsCode().compareTo(o2.getMtGoodsCode());
            }
        });

        Collections.sort(goodsitems, new Comparator<MtFoodconsumgoodsitem>() {
            @Override
            public int compare(MtFoodconsumgoodsitem o1, MtFoodconsumgoodsitem o2) {
                return o1.getMtGoodsCode().compareTo(o2.getMtGoodsCode());
            }
        });
        //2.逐个比对
        for(int i=0;i< existCardItems.size();i++){
            MtFoodcostcarditem existCardItem = existCardItems.get(i);
            MtFoodconsumgoodsitem newCardItem = goodsitems.get(i);
            //物品编码必须相同
            if(!existCardItem.getMtGoodsCode().equals(newCardItem.getMtGoodsCode())){
                return true;
            }

            //计算出来美团菜品消耗物品明细表中该菜品的成本卡消耗数量、也就是每一份菜品消耗的物品数量
            setConsumptionamountInCostCard(newCard,newCardItem);

            //数量与已存在的成本卡数量之间存在差异，则认为成本卡已经变更
            if(newCardItem.getConsumptionamountInCostcard().compareTo(existCardItem.getAmount())!=0){
                return true;
            }
        }
        return false;
    }

    /**
     * 计算美团菜品消耗物料明细表中每一物品的成本卡消耗数量：每一份菜品的消耗数量
     * @param mtFoodconsumitem        美团菜品消耗数据 - 某一菜品的数据
     * @param mtFoodconsumgoodsitem   菜品消耗数据对应的物品消耗明细表 - 某一菜品下某一物品的消耗明细
     */
    public void setConsumptionamountInCostCard(MtFoodconsumitem mtFoodconsumitem,MtFoodconsumgoodsitem mtFoodconsumgoodsitem){
            //菜品消耗明细表中，已出库数量+未出库数量，是消耗数量？
            BigDecimal foodConsumAmount = new BigDecimal(mtFoodconsumitem.getOutamount()).add(new BigDecimal(mtFoodconsumitem.getNotoutamount()));
            //物料的消耗数量 / 菜品数量 = 该菜品每一份消耗的物品数量，即成本卡数量
            mtFoodconsumgoodsitem.setConsumptionamountInCostcard(mtFoodconsumgoodsitem.getConsumptionamount().divide(
                    foodConsumAmount,6, RoundingMode.HALF_UP));
    }

    /**
     * 从美团菜品消耗主表及明细表数据，生成美团成本卡主表数据
     * @param newCard
     * @param mtfoodconsum
     */
    private void prepareFoodCostCard(MtFoodcostcard newCard, MtFoodconsum mtfoodconsum, MtFoodconsumitem mtFoodconsumitem) {
        newCard.setFoodskuid(mtFoodconsumitem.getFoodskuid());
        newCard.setFoodname(mtFoodconsumitem.getFoodname());

        newCard.setMtShopId(mtfoodconsum.getMtShopld());

        newCard.setEffectiveDate(new Date(mtfoodconsum.getBiztime()));
        newCard.setFoodspec(mtFoodconsumitem.getFoodspec());
        newCard.setCreateBy("1");
        newCard.setCreateTime(DateUtils.getNowDate());
        //状态正常
        newCard.setStatus(100);
    }





}
